﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Ndo.Maths
{
    public sealed class Variant : Arithmetic<Variant>
    {
        public Variant(IArithmetic a)
        {
            if (a == null)
                throw new ArgumentNullException();
            value = a;
        }
        public override string ToString()
        {
            return value.ToString();
        }
        //public static Variant GetVariant<T>(T value)
        //    where T : Number<T>, new()
        //{
        //    if(value == null)
        //        return null;
        //    return new Variant(value);
        //}
        private static bool Check(ref Variant v1, ref Variant v2)
        {
            if (v1 == null || v2 == null)
                return false;
            Type t1 = v1.value.GetType(), t2 = v2.value.GetType();
            if(t1 == t2)
                return true;
            if (Convertor.CanImplicit(t2, t1))
            {
                v2 = new Variant((IArithmetic)Convertor.Implicit(v2.value, t1));
                return true;
            }
            if (Convertor.CanImplicit(t1, t2))
            {
                v1 = new Variant((IArithmetic)Convertor.Implicit(v1.value, t2));
                return true;
            }
            return false;
        }
        private readonly IArithmetic value;
        public static Variant operator +(Variant v1, Variant v2)
        {
            if (Check(ref v1, ref v2))
            {
                return new Variant((IArithmetic)v1.value.Add(v2.value));
            }
            throw new InvalidOperationException();
        }
        public static Variant operator -(Variant v1, Variant v2)
        {
            if (Check(ref v1, ref v2))
            {
                return new Variant((IArithmetic)v1.value.SubtractedFrom(v2.value));
            }
            throw new InvalidOperationException();
        }
        public static Variant operator *(Variant v1, Variant v2)
        {
            if (Check(ref v1, ref v2))
            {
                return new Variant((IArithmetic)v1.value.MultipliedBy(v2.value));
            }
            throw new InvalidOperationException();
        }
        public static Variant operator /(Variant v1, Variant v2)
        {
            if (Check(ref v1, ref v2))
            {
                return new Variant((IArithmetic)v1.value.DividedBy(v2.value));
            }
            throw new InvalidOperationException();
        }
    }
}
